require('../js/global.js');
var crypto  = require('crypto');
var http = require('http');
var url = require('url');
var csv = require('../js/csv.js');
var ServerManager = require('../js/servers.js').ServerManager;

var spliter = '\t';
var dipPort = config.platform.dip.port;
var dipURL = util.format('%s:%d', config.server.host.mid.url, dipPort);
var dipKey = 'molingkeji123';

global.gProcessName = 'dip';
global.gServers = new ServerManager();

gServers.load({slave:true, native:true}, function(err) {
    if (err) {
        LOG(util.format('load failed, %j', err));
        process.exit(1);
    }

    startWebServer({
        name: gProcessName,
        port: config.platform.dip.port,
        timeout: 600*1000,
    });

    setInterval(function(){
        gServers.loadGame(function(err) {});
    }, 600*1000);
});


function startWebServer(options) {
    var name = options.name;
    var port = options.port;
    var timeout = options.timeout;

    LOG(util.format('%s start', name));
    var webServer = http.createServer(function(req, res) {
        var reqObj = url.parse(req.url, true);
        var query = reqObj.query || {};
        var path = reqObj.pathname.split('/');

        if( req.method == 'POST' ) {
            req.connection.destroy();
            return;
        }
         
        req.on('end', function() {
            var base = path[1];

            if ('serversByJson' == base) {
                serversByJson(query, res);
            } else if ('QuerySystem' == base) {
                var handler = QuerySystem[path[2]];
                if (handler) {
                    var resp = {Result:0};
                    if (!query.time || !query.sign) {
                        resp.Result = -101;
                        res.writeHead(200, common.htmlHeaders);
                        res.end(JSON.stringify(resp));
                        return;
                    }

                    var md5 = crypto.createHash('md5');
                    var md5Sign = md5.update(util.format('time=%s&key=%s', query.time, dipKey)).digest('hex');
                    if (md5Sign != query.sign) {
                        resp.Result = -103;
                        res.writeHead(200, common.htmlHeaders);
                        res.end(JSON.stringify(resp));
                        return;
                    }

                    handler(query, resp, function() {
                        res.writeHead(200, common.htmlHeaders);
                        res.end(JSON.stringify(resp));
                    });
                } else {
                    res.writeHead(404, {"Content-Type": "text/plain"});
                    res.end('404 unknown handler');
                }
            } else {
                res.writeHead(404, {"Content-Type": "text/plain"});
                res.end('404');
            }
        });

        req.resume();

    });
    
    webServer.listen(port);
    webServer.timeout = timeout;

    var pidFile = util.format('%s.pid', name);
    process.on('SIGINT', function() {
        exit();
    });

    process.on('SIGTERM', function() {
        exit();
    });

    process.on('uncaughtException', function (err) {  
        LOG(err.stack);        
    });

    function exit() {
        LOG(util.format('%s shutdown', name));
        fs.existsSync(pidFile) && fs.unlinkSync(pidFile);
        process.exit();
    }
}


////////////////////////////////////////////////////////////////////

function offsetServerId(sid) {
    return config.game.osid(sid);
}

function sidFromOffsetId(osid) {
    return config.game.sidFromOsid(osid);
}

function serversByJson(query, res) {
    var servers = gServers.gameServers;
    var resp = [];
    for (var id in servers) {
        var server = servers[id];
        if (!server.isValid()) {
            continue;
        }

        var time = server.time + ':00';
        var osid = offsetServerId(server.id);
        resp.push({
            pid: config.platform.id,
            pname: config.platform.name,
            sid: osid,
            sname: 's'+osid,
            domain: dipURL,
            time: time,
            update: time,
        });
    }

	res.writeHead(200, common.htmlHeaders);
	res.end(JSON.stringify(resp));
}

var QuerySystem = {};

QuerySystem.OnlineCount = function(query, resp, callback) {
    resp.WorldList = [];

    async.each(gServers.getSids(), function(sid, cb) {
        var server = gServers.gameServers[sid];
        var url = util.format('http://%s:%d?act=online', server.hostIP, server.gatewayPort);
        common.httpGet(url, function(data) {
            resp.data = data;
            if (data) {
                var count = +data;
                resp.WorldList.push({
                    WorldID: offsetServerId(sid),
                    AccountCount: count,
                    PlayerCount: count,
                });
            }
            cb();
        }, false);
    }, function(err) {
        callback();
    });
}

QuerySystem.AccountCount = function(query, resp, callback) {
    resp.WorldList = [];

    async.each(gServers.getSids(), function(sid, cb) {
        var db = gServers.getGameDB(sid);
        if (!db) {
            cb();
            return;
        }

        var dbPlat = db.collection('pay');
        dbPlat.count({}, function(err, count) {
            resp.WorldList.push({
                WorldID: offsetServerId(sid),
                AccountCount: count
            });
            cb();
        });
    }, function(err) {
        callback();
    });
}

QuerySystem.PlayerCount = function(query, resp, callback) {
    resp.WorldList = [];

    async.each(gServers.getSids(), function(sid, cb) {
        var db = gServers.getGameDB(sid);
        if (!db) {
            cb();
            return;
        }

        var dbUser = db.collection('user');
        dbUser.count({}, function(err, count) {
            resp.WorldList.push({
                WorldID: offsetServerId(sid),
                PlayerCount: count
            });
            cb();
        });
    }, function(err) {
        callback();
    });
}

QuerySystem.ServerRecharge = function(query, resp, callback) {
    resp.Recharge = 0;

    var sid = sidFromOffsetId(+query.WorldID);
    var db = gServers.getGameDB(sid);
    if (!db) {
        callback();
        return;
    }

    var dbPay = db.collection('pay');
	var cursor = dbPay.find({}, {'amt':1});
	var count = 0;
	cursor.each(function(err, item){
        if (err || cursor.isClosed()) {
            resp.Recharge = count;
            callback();
            return;
        }

        count += parseInt(item.amt);
	});
}
